package com.xucia.jsponic.data;

import java.security.acl.Acl;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import com.xucia.jsponic.datasource.PersistableInitializer;


public class Templates {
	static Map<String,PersistableImpl> basisCache;
	// TODO: Should really come up with of reloading this cache, if the templates change we need a reboot right now
	public static PersistableImpl findTemplate(String name) {
		PersistableImpl retValue = basisCache.get(name);
		if (retValue != null)
			return retValue;
		retValue = (PersistableImpl) ((Persistable) DataSourceManager.getRootObject().get(GlobalData.TEMPLATES_FIELD)).get(name);
		basisCache.put(name,retValue);
		return retValue;
	}
	public static void reset() {
		basisClassCache = null;
	}
	static Map<ObjectId,Class<? extends Persistable>> basisClassCache;
	static ObjectId javaClassBasisesId;
	public static Persistable getBasisForClass(Class<? extends Persistable> clazz) {
		getClassForObject(ObjectId.idForObject(DataSourceManager.getRootSource(),"0")); // make sure it is loaded
		for (Entry<ObjectId,Class<? extends Persistable>> entry : basisClassCache.entrySet())
			if (entry.getValue() == clazz)
				return entry.getKey().getTarget();
		return null;
	}
	public static Class<? extends Persistable> getClassForObject(Object id) {
		if (basisClassCache == null) {
			basisClassCache = new HashMap<ObjectId,Class<? extends Persistable>>();
			try {
				DataSourceManager.getRootSource().mapObject(new PersistableInitializer() {
					public void setSchema(Persistable structure) {}
					public void setCacheLevel(long time) {}
					public void finished() {}
					public Persistable getInitializingObject() {return null;}
					public void initializeByPrototype(ObjectId prototypeId) {}
					public void initializeFunction(String source, boolean authorizedOnServer) {}
					public void initializeList(Iterator iterator) {}
					public void initializeObject(PersistableImpl object) {}
					public void setAcl(Acl acl) {}
					public void setParent(ObjectId objectToInheritFrom) {}
					public void setPersistentAcl(ObjectId aclId) {}
					public void setProperty(String name, Object value) {
						if ("javaClassBasises".equals(name))
							javaClassBasisesId = (ObjectId) value;
					}
				}, "0");
				if (javaClassBasisesId!=null)
				  javaClassBasisesId.source.mapObject(new PersistableInitializer() {					
					public void setSchema(Persistable structure) {}
					public void setCacheLevel(long time) {}
					public void finished() {}
					public Persistable getInitializingObject() {return null;}
					public void initializeByPrototype(ObjectId prototypeId) {}
					public void initializeFunction(String source, boolean authorizedOnServer) {}
					public void initializeList(Iterator iterator) {
						while (iterator.hasNext()) {
							final ObjectId classBasisId = (ObjectId) iterator.next();
							try {
								classBasisId.source.mapObject(new PersistableInitializer() {	
									public void setSchema(Persistable structure) {}
									public void setCacheLevel(long time) {}
									public void finished() {}
									public Persistable getInitializingObject() {return null;}
									public void initializeByPrototype(ObjectId prototypeId) {}
									public void initializeFunction(String source, boolean authorizedOnServer) {}
									public void initializeList(Iterator iterator) {}
									public void initializeObject(PersistableImpl object) {}
									public void setAcl(Acl acl) {}
									public void setParent(ObjectId objectToInheritFrom) {}
									public void setPersistentAcl(ObjectId aclId) {}
									public void setProperty(String name, Object value) {
										if ("className".equals(name)) {
											try {
												if (value instanceof LazyPropertyId) {
													value = ((LazyPropertyId)value).getTarget();
												}
												basisClassCache.put(classBasisId, (Class<? extends Persistable>) Class.forName((String) value));
											} catch (ClassNotFoundException e) {
												throw new RuntimeException(e);
											}
										}
									}
								}, classBasisId.subObjectId);
							} catch (Exception e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
						
					}
					public void initializeObject(PersistableImpl object) {}
					public void setAcl(Acl acl) {}
					public void setParent(ObjectId objectToInheritFrom) {}
					public void setPersistentAcl(ObjectId aclId) {}
					public void setProperty(String name, Object value) {}
				}, javaClassBasisesId.subObjectId);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			/*List<Persistable> javaClassBasises = (List<Persistable>) DataSourceManager.getRootObject().get("javaClassBasises");
			
			boolean isEmpty = true;
			for (Persistable classBasis : javaClassBasises)
				try {
					isEmpty =false;
					basisClassCache.put(classBasis.getId(), Class.forName((String) classBasis.get(GlobalData.CLASS_NAME_FIELD)));					
				}
				catch (Exception e) {
					e.printStackTrace();
				}
			if (isEmpty)
				throw new RuntimeException("no templates");*/
		}
		return basisClassCache.get(id);
	}
}
